'''
basic "operating system" services

This module implements a subset of the corresponding `CPython` module, as
described below.

For more information, refer to the original `CPython` documentation: [os](https://docs.python.org/3.5/library/os.html#module-os).

The `os` module contains functions for filesystem access and mounting, terminal
redirection and duplication, and the `uname` and `urandom` functions.

[View Doc](https://docs.micropython.org/en/latest/library/os.html)
'''
import typing


# General functions
def uname() -> tuple:
	'''
	Return a tuple (possibly a named tuple) containing information about the
	underlying machine and/or its operating system.

	The tuple has five fields in the following order, each of them being a string:

	- `sysname` – the name of the underlying system
	- `nodename` – the network name (can be the same as sysname)
	- `release` – the version of the underlying system
	- `version` – the MicroPython version and build date
	- `machine` – an identifier for the underlying hardware (eg board, CPU)
	'''

def urandom(n: int) -> bytes:
	'''
	Return a bytes object with `n` random bytes.

	Whenever possible, it is generated by the hardware random number generator.
	'''

# Filesystem access
def chdir(path: str):
	'''Change current directory.'''

def getcwd() -> str:
	'''Get the current directory.'''

@typing.overload
def ilistdir():
	'''
	This function returns an iterator which then yields tuples corresponding to
	the entries in the directory that it is listing.

	It lists the current directory.

	The tuples have the form `(name, type, inode[, size])`:

	- `name` is a string (or bytes if dir is a bytes object) and is the name of
	the entry;

	- `type` is an integer that specifies the type of the entry, with 0x4000 for
	directories and 0x8000 for regular files;

	- `inode` is an integer corresponding to the inode of the file, and may be 0
	for filesystems that don’t have such a notion.

	- Some platforms may return a 4-tuple that includes the entry’s size.

		For file entries, size is an integer representing the size of the file
		or -1 if unknown.

		Its meaning is currently undefined for directory entries.
	'''

@typing.overload
def ilistdir(dir: str):
	'''
	This function returns an iterator which then yields tuples corresponding to
	the entries in the directory that it is listing.

	It lists the directory given by `dir`.

	The tuples have the form `(name, type, inode[, size])`:

	- `name` is a string (or bytes if dir is a bytes object) and is the name of
	the entry;

	- `type` is an integer that specifies the type of the entry, with 0x4000 for
	directories and 0x8000 for regular files;

	- `inode` is an integer corresponding to the inode of the file, and may be 0
	for filesystems that don’t have such a notion.

	- Some platforms may return a 4-tuple that includes the entry’s size.

		For file entries, size is an integer representing the size of the file
		or -1 if unknown.

		Its meaning is currently undefined for directory entries.
	'''

@typing.overload
def listdir():
	'''List the current directory.'''

@typing.overload
def listdir(dir: str):
	'''List the given directory.'''

def mkdir(path: str):
	'''Create a new directory.'''

def remove(path: str):
	'''Remove a file.'''

def rmdir(path: str):
	'''Remove a directory.'''

def rename(old_path: str, new_path: str):
	'''Rename a file.'''

def stat(path: str):
	'''Get the status of a file or directory.'''

def statvfs(path: str) -> tuple:
	'''
	Get the status of a filesystem.

	Returns a tuple with the filesystem information in the following order:

	- `f_bsize` – file system block size
	- `f_frsize` – fragment size
	- `f_blocks` – size of fs in f_frsize units
	- `f_bfree` – number of free blocks
	- `f_bavail` – number of free blocks for unprivileged users
	- `f_files` – number of inodes
	- `f_ffree` – number of free inodes
	- `f_favail` – number of free inodes for unprivileged users
	- `f_flag` – mount flags
	- `f_namemax` – maximum filename length

	Parameters related to inodes: `f_files`, `f_ffree`, `f_avail` and the
	`f_flags` parameter may return 0 as they can be unavailable in a
	port-specific implementation.
	'''

def sync():
	'''Sync all filesystems.'''

# Terminal redirection and duplication
def dupterm(stream_object, index: int = 0, /):
	'''
	Duplicate or switch the MicroPython terminal (the REPL) on the given
	stream-like object.

	The `stream_object` argument must be a native stream object, or derive from
	`io.IOBase` and implement the `readinto()` and `write()` methods.

	The stream should be in non-blocking mode and `readinto()` should return None
	if there is no data available for reading.

	After calling this function all terminal output is repeated on this stream,
	and any input that is available on the stream is passed on to the terminal
	input.

	The `index` parameter should be a non-negative integer and specifies which
	duplication slot is set.

	A given port may implement more than one slot (slot 0 will always be available)
	and in that case terminal input and output is duplicated on all the slots that are set.

	If None is passed as the `stream_object` then duplication is cancelled on the
	slot given by `index`.

	The function returns the previous stream-like object in the given slot.
	'''

# Filesystem mounting
# The following functions and classes have been moved to the vfs module.
# They are provided in this module only for backwards compatibility and will be
# removed in version 2 of MicroPython.
def mount(fsobj, mount_point, *, readonly):
	'''See `vfs.mount`.'''

def umount(mount_point):
	'''See `vfs.umount`.'''


class VfsFat(object):
	'''See `vfs.VfsFat`.'''
	def __init__(self, block_dev): ...


class VfsLfs1(object):
	'''See `vfs.VfsLfs1`.'''

	def __init__(self, block_dev, readsize=32, progsize=32, lookahead=32): ...


class VfsLfs2(object):
	'''See `vfs.VfsLfs2`.'''
	def __init__(self, block_dev, readsize=32, progsize=32, lookahead=32, mtime=True): ...


class VfsPosix(object):
	'''See `vfs.VfsPosix`.'''
	def __init__(self, root=None): ...
